"""
使用 pytest-benchmark 框架进行专业性能测试

安装依赖:
pip install pytest pytest-benchmark

运行测试:
pytest benchmark_test.py -v                    # 基本测试
pytest benchmark_test.py --benchmark-only      # 只运行基准测试
pytest benchmark_test.py --benchmark-sort=mean # 按平均时间排序
pytest benchmark_test.py --benchmark-json=results.json  # 保存JSON结果
pytest benchmark_test.py --benchmark-histogram # 生成直方图
"""

import pytest
from string_permutation import (
    permute_recursive,
    permute_iterative,
    permute_lexicographic,
    permute_heap,
    permute_generator
)


class TestPermutationCorrectness:
    """测试算法正确性"""
    
    @pytest.fixture
    def test_cases(self):
        """测试用例数据"""
        return [
            ("a", 1),
            ("ab", 2),
            ("abc", 6),
            ("abcd", 24),
        ]
    
    def test_recursive_correctness(self, test_cases):
        """测试递归方法的正确性"""
        for string, expected_count in test_cases:
            result = permute_recursive(string)
            assert len(result) == expected_count
            assert len(set(result)) == len(result)  # 无重复
    
    def test_iterative_correctness(self, test_cases):
        """测试迭代方法的正确性"""
        for string, expected_count in test_cases:
            result = permute_iterative(string)
            assert len(result) == expected_count
            assert len(set(result)) == len(result)  # 无重复
    
    def test_lexicographic_correctness(self, test_cases):
        """测试字典序方法的正确性"""
        for string, expected_count in test_cases:
            result = permute_lexicographic(string)
            assert len(result) == expected_count
            assert len(set(result)) == len(result)  # 无重复
    
    def test_heap_correctness(self, test_cases):
        """测试Heap算法的正确性"""
        for string, expected_count in test_cases:
            result = permute_heap(string)
            assert len(result) == expected_count
            assert len(set(result)) == len(result)  # 无重复
    
    def test_generator_correctness(self, test_cases):
        """测试生成器方法的正确性"""
        for string, expected_count in test_cases:
            result = list(permute_generator(string))
            assert len(result) == expected_count
            assert len(set(result)) == len(result)  # 无重复
    
    def test_all_algorithms_consistency(self):
        """测试所有算法结果一致性"""
        test_string = "abc"
        
        recursive_result = sorted(permute_recursive(test_string))
        iterative_result = sorted(permute_iterative(test_string))
        lexicographic_result = sorted(permute_lexicographic(test_string))
        heap_result = sorted(permute_heap(test_string))
        generator_result = sorted(list(permute_generator(test_string)))
        
        assert recursive_result == iterative_result
        assert iterative_result == lexicographic_result
        assert lexicographic_result == heap_result
        assert heap_result == generator_result


class TestPermutationBenchmark:
    """性能基准测试"""
    
    # 小规模测试数据
    @pytest.fixture
    def small_data(self):
        return "abc"  # 3! = 6
    
    # 中等规模测试数据
    @pytest.fixture
    def medium_data(self):
        return "abcd"  # 4! = 24
    
    # 较大规模测试数据
    @pytest.fixture
    def large_data(self):
        return "abcde"  # 5! = 120
    
    # 递归方法基准测试
    def test_benchmark_recursive_small(self, benchmark, small_data):
        """递归方法 - 小规模数据基准测试"""
        result = benchmark(permute_recursive, small_data)
        assert len(result) == 6
    
    def test_benchmark_recursive_medium(self, benchmark, medium_data):
        """递归方法 - 中等规模数据基准测试"""
        result = benchmark(permute_recursive, medium_data)
        assert len(result) == 24
    
    def test_benchmark_recursive_large(self, benchmark, large_data):
        """递归方法 - 较大规模数据基准测试"""
        result = benchmark(permute_recursive, large_data)
        assert len(result) == 120
    
    # 迭代方法基准测试
    def test_benchmark_iterative_small(self, benchmark, small_data):
        """迭代方法 - 小规模数据基准测试"""
        result = benchmark(permute_iterative, small_data)
        assert len(result) == 6
    
    def test_benchmark_iterative_medium(self, benchmark, medium_data):
        """迭代方法 - 中等规模数据基准测试"""
        result = benchmark(permute_iterative, medium_data)
        assert len(result) == 24
    
    def test_benchmark_iterative_large(self, benchmark, large_data):
        """迭代方法 - 较大规模数据基准测试"""
        result = benchmark(permute_iterative, large_data)
        assert len(result) == 120
    
    # 字典序方法基准测试
    def test_benchmark_lexicographic_small(self, benchmark, small_data):
        """字典序方法 - 小规模数据基准测试"""
        result = benchmark(permute_lexicographic, small_data)
        assert len(result) == 6
    
    def test_benchmark_lexicographic_medium(self, benchmark, medium_data):
        """字典序方法 - 中等规模数据基准测试"""
        result = benchmark(permute_lexicographic, medium_data)
        assert len(result) == 24
    
    def test_benchmark_lexicographic_large(self, benchmark, large_data):
        """字典序方法 - 较大规模数据基准测试"""
        result = benchmark(permute_lexicographic, large_data)
        assert len(result) == 120
    
    # Heap算法基准测试
    def test_benchmark_heap_small(self, benchmark, small_data):
        """Heap算法 - 小规模数据基准测试"""
        result = benchmark(permute_heap, small_data)
        assert len(result) == 6
    
    def test_benchmark_heap_medium(self, benchmark, medium_data):
        """Heap算法 - 中等规模数据基准测试"""
        result = benchmark(permute_heap, medium_data)
        assert len(result) == 24
    
    def test_benchmark_heap_large(self, benchmark, large_data):
        """Heap算法 - 较大规模数据基准测试"""
        result = benchmark(permute_heap, large_data)
        assert len(result) == 120
    
    # 生成器方法基准测试
    def test_benchmark_generator_small(self, benchmark, small_data):
        """生成器方法 - 小规模数据基准测试"""
        result = benchmark(lambda x: list(permute_generator(x)), small_data)
        assert len(result) == 6
    
    def test_benchmark_generator_medium(self, benchmark, medium_data):
        """生成器方法 - 中等规模数据基准测试"""
        result = benchmark(lambda x: list(permute_generator(x)), medium_data)
        assert len(result) == 24
    
    def test_benchmark_generator_large(self, benchmark, large_data):
        """生成器方法 - 较大规模数据基准测试"""
        result = benchmark(lambda x: list(permute_generator(x)), large_data)
        assert len(result) == 120


class TestPermutationMemoryBenchmark:
    """内存使用基准测试"""
    
    @pytest.fixture
    def memory_data(self):
        return "abcdef"  # 6! = 720
    
    def test_memory_usage_iterative(self, benchmark, memory_data):
        """测试迭代方法的内存使用"""
        import tracemalloc
        
        def measure_memory():
            tracemalloc.start()
            result = permute_iterative(memory_data)
            current, peak = tracemalloc.get_traced_memory()
            tracemalloc.stop()
            return result, peak
        
        result, peak_memory = benchmark(measure_memory)
        assert len(result) == 720
        # 记录峰值内存使用
        print(f"\n峰值内存使用: {peak_memory / 1024:.2f} KB")
    
    def test_memory_usage_generator(self, benchmark, memory_data):
        """测试生成器方法的内存使用"""
        import tracemalloc
        
        def measure_memory():
            tracemalloc.start()
            result = []
            count = 0
            for perm in permute_generator(memory_data):
                result.append(perm)
                count += 1
                if count >= 100:  # 只生成前100个
                    break
            current, peak = tracemalloc.get_traced_memory()
            tracemalloc.stop()
            return result, peak
        
        result, peak_memory = benchmark(measure_memory)
        assert len(result) == 100
        # 记录峰值内存使用
        print(f"\n峰值内存使用: {peak_memory / 1024:.2f} KB")


class TestPermutationScalability:
    """可扩展性测试"""
    
    @pytest.mark.parametrize("length,expected", [
        (2, 2),
        (3, 6),
        (4, 24),
        (5, 120),
    ])
    def test_iterative_scalability(self, benchmark, length, expected):
        """测试迭代方法的可扩展性"""
        test_string = ''.join(chr(ord('a') + i) for i in range(length))
        result = benchmark(permute_iterative, test_string)
        assert len(result) == expected
    
    @pytest.mark.parametrize("length,expected", [
        (2, 2),
        (3, 6),
        (4, 24),
        (5, 120),
    ])
    def test_heap_scalability(self, benchmark, length, expected):
        """测试Heap算法的可扩展性"""
        test_string = ''.join(chr(ord('a') + i) for i in range(length))
        result = benchmark(permute_heap, test_string)
        assert len(result) == expected


if __name__ == "__main__":
    # 可以直接运行此文件进行快速测试
    print("请使用 pytest 命令运行基准测试:")
    print("pytest benchmark_test.py -v")
    print("pytest benchmark_test.py --benchmark-only")
    print("pytest benchmark_test.py --benchmark-sort=mean")
